package com.gsp.gspframework.proxy;

import com.gsp.gspframework.annotation.Transactional;
import com.gsp.gspframework.helper.DatabaseHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

public class TransactionalProxy implements Proxy {

    private static final Logger log = LoggerFactory.getLogger(TransactionalProxy.class);

    private static final ThreadLocal<Boolean> FLAG_HOLDER = ThreadLocal.withInitial(() -> false);

    @Override
    public Object doProxy(ProxyChain proxyChain) throws Throwable {
        Object result;
        Boolean flag = FLAG_HOLDER.get();
        Method targetMethod = proxyChain.getTargetMethod();
        if (!flag && targetMethod.isAnnotationPresent(Transactional.class)) {
            FLAG_HOLDER.set(true);
            try {
                DatabaseHelper.beginTransactional();
                result = proxyChain.doProxyChain();
                DatabaseHelper.commitTransactional();
            } catch (Exception e) {
                log.error("transactionalProxy do proxy error", e);
                DatabaseHelper.rollBackTransactional();
                throw e;
            } finally {
                FLAG_HOLDER.remove();
            }
        } else {
            result = proxyChain.doProxyChain();
        }
        return result;
    }
}
